package com.glodon.paas.job.server.service.impl;

import static com.glodon.paas.job.JobConstants.*;
import static com.glodon.paas.job.model.TaskStatus.*;
import static com.glodon.paas.job.util.JobUtil.*;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.listener.AbstractMessageListenerContainer;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.stereotype.Component;

import com.glodon.paas.job.JobConstants;
import com.glodon.paas.job.model.Task;
import com.glodon.paas.job.server.service.NotifyService;
import com.glodon.paas.job.server.service.TaskService;

@Component
public class TaskResultListener implements MessageListener {
    private static final Logger logger = LoggerFactory.getLogger(TaskResultListener.class);
    @Autowired
    private NotifyService notifyService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ConnectionFactory connectionFactory;
    private AbstractMessageListenerContainer listenerContainer;
    @Value("${job.server.max.fail.count}")
    private int maxFailCount = -1;

    @PostConstruct
    public void init() {
        listenerContainer = new DefaultMessageListenerContainer();
        listenerContainer.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
        listenerContainer.setConnectionFactory(connectionFactory);
        listenerContainer.setDestinationName(AGENT_RESULT_QUEUE);
        listenerContainer.setMessageListener(this);
        listenerContainer.initialize();
        listenerContainer.start();
    }

    @PreDestroy
    public void stop() {
        listenerContainer.shutdown();
        listenerContainer.stop();
    }

    @Override
    public void onMessage(Message msg) {
        try {
            Task task = Task.createTask(msg);
            if (task.getStatus() == success || task.getStatus() == failure)
                task.setEndTime(getMessageInTime(msg));
            onTask(task);
        } catch (Exception e) {
            logger.warn("exception ignored", e);
        }
    }

    private void onTask(Task task) throws Exception {
        if (maxFailCount > 0 && task.getFailCount() > maxFailCount) {
            taskService.cancelTask(task);
        } else {
            taskService.save(task);
        }
        String callback = (String) task.getValue(JobConstants.TASK_CALLBACK);
        if (callback != null)
            notifyService.notify(task, callback);
    }

    public void setTaskService(TaskService taskService) {
        this.taskService = taskService;
    }

    public void setNotifyService(NotifyService notifyService) {
        this.notifyService = notifyService;
    }

    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }
}
